package com.bosssoft.g1.authserver.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.bosssoft.g1.authserver.constant.MessageConstant;
import com.bosssoft.g1.authserver.domain.SecurityUser;
import com.bosssoft.g1.authserver.entity.Tenant;
import com.bosssoft.g1.authserver.entity.User;
import com.bosssoft.g1.authserver.mapper.TenantMapper;
import com.bosssoft.g1.authserver.mapper.UserMapper;
import com.bosssoft.g1.authserver.entity.Role;
import com.bosssoft.g1.authserver.entity.UserRole;
import com.bosssoft.g1.authserver.mapper.RoleMapper;
import com.bosssoft.g1.authserver.mapper.UserRoleMapper;
import com.bosssoft.g1.authserver.vo.UserLoginVO;
import com.bosssoft.g1.common.exception.parse.CustomException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户管理业务类
 * Created by macro on 2020/6/19.
 */
@Service
public class UserServiceImpl implements UserDetailsService {

//    private List<UserDTO> userList;
//    @Autowired
//    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private TenantMapper tenantMapper;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        List<User> users = userMapper.selectByCode(username);

        if (CollUtil.isEmpty(users)) {
            throw new UsernameNotFoundException(MessageConstant.USERNAME_PASSWORD_ERROR);
        }
        User user = users.get(0);
        // 查询权限
        List<String> roleName = selectUserRole(user.getId());

        SecurityUser securityUser = new SecurityUser(user, roleName);
        System.out.println(securityUser);
        if (!securityUser.isEnabled()) {
            System.out.println("isEnabled");
            throw new DisabledException(MessageConstant.ACCOUNT_DISABLED);
        } else if (!securityUser.isAccountNonLocked()) {
            System.out.println("isAccountNonLocked");
            throw new LockedException(MessageConstant.ACCOUNT_LOCKED);
        } else if (!securityUser.isAccountNonExpired()) {
            System.out.println("isAccountNonExpired");
            throw new AccountExpiredException(MessageConstant.ACCOUNT_EXPIRED);
        } else if (!securityUser.isCredentialsNonExpired()) {
            System.out.println("isCredentialsNonExpired");
            throw new CredentialsExpiredException(MessageConstant.CREDENTIALS_EXPIRED);
        }
        return securityUser;
    }


    private List<String> selectUserRole(Long userId) {
        Example example = new Example(UserRole.class);
        example.createCriteria().andEqualTo("userId", userId);
        List<UserRole> userRoles = userRoleMapper.selectByExample(example);
        List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(roleIds)) {
            return new ArrayList<>();
        }
        example = new Example(Role.class);
        example.createCriteria().andIn("id", roleIds);
        List<Role> roles = roleMapper.selectByExample(example);
        List<String> roleName = roles.stream().map(Role::getName).collect(Collectors.toList());
        return roleName;
    }

    public UserLoginVO check(String username, String password, String account) throws CustomException {
        // 获取用户
        Example example = new Example(User.class);
        example.createCriteria().andEqualTo("code", username);
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtil.isEmpty(users)) {
            return null;
        } else if (users.size() > 1) {
            throw new CustomException("code重复");
        }

        User user = users.get(0);

        // 校验password
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode(password);
        System.out.println("加密后的密码是" + encode);
        if (bCryptPasswordEncoder.matches(user.getPassword(), password)) {
            System.out.println("密码错误");
            throw new CustomException("密码错误");
        }

        // 校验account
        Tenant tenant = tenantMapper.selectByPrimaryKey(user.getTenantId());
        if (ObjectUtil.isNotNull(tenant) && !StrUtil.equals(tenant.getAccount(), account)) {
            System.out.println("密码错误");
            throw new CustomException("account错误");
        }

        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtil.copyProperties(user, userLoginVO);
        userLoginVO.setTenantName(tenant.getName());
        return userLoginVO;
    }
}
